﻿using System;
using System.Windows.Forms;
using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Discovery;
using Google.Apis.Samples.Helper;
using Google.Apis.Tasks.v1;
using Google.Apis.Tasks.v1.Data;
using Google.Apis.Util;
using System.IO;

namespace G_Tasks
{
    /// <summary>
    /// Note Manager
    /// A more complex example for the tasks API.
    /// </summary>
    internal static class Program
    {
        private static string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + Path.DirectorySeparatorChar + "G-Tasks" + Path.DirectorySeparatorChar;
        private static string STORAGE;
        private static string KEY;
        /// <summary>
        /// The remote service on which all the requests are executed.
        /// </summary>
        public static TasksService Service { get; private set; }

        private static IAuthenticator CreateAuthenticator()
        {
            var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
            provider.ClientIdentifier = ClientCredentials.ClientID;
            provider.ClientSecret = ClientCredentials.ClientSecret;
            return new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthentication);
        }

        private static IAuthorizationState GetAuthentication(NativeApplicationClient client)
        {
            string scope = TasksService.Scopes.Tasks.GetStringValue();

            // Check if there is a cached refresh token available.
            IAuthorizationState state = null;
            try
            {
                state = AuthorizationMgr.GetCachedRefreshToken(STORAGE, KEY);
            }
            catch
            {
                if (MessageBox.Show("Get auth token failed. Try generate new?", "Auth failed", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    File.Delete(appData + "data.dat");
                else
                    Environment.Exit(-1);
            }

            if (state != null)
            {
                try
                {
                    client.RefreshToken(state);
                    return state; // Yes - we are done.
                }
                catch (DotNetOpenAuth.Messaging.ProtocolException ex)
                {
                    CommandLine.WriteError("Using existing refresh token failed: " + ex.Message);
                }
            }

            // Retrieve the authorization from the user.
            state = AuthorizationMgr.RequestNativeAuthorization(client, scope);
            AuthorizationMgr.SetCachedRefreshToken(STORAGE, KEY, state);
            return state;
        }

        public static void RefreshToken()
        {
            Service = new TasksService(CreateAuthenticator());
        }

        // Pro vygenerování náhodného klíče
        private static Random random = new Random((int)DateTime.Now.Ticks);
        private static string RandomString(int size)
        {
            System.Text.StringBuilder builder = new System.Text.StringBuilder();
            char ch;
            for (int i = 0; i < size; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }

            return builder.ToString();
        }

        private static void LoadData()
        {
            using (StreamReader sr = new StreamReader(appData + "data.dat"))
            {
                STORAGE = sr.ReadLine();
                KEY = sr.ReadLine();
            }
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Vygenerování náhodných údajů pro přístup k datům uložených na serverech - je to ověřování aplikace, z ňákýho důvodu se tomu asi nelíbí, když to používá vís lidí, tedy jsme to udělal takto
            if (!Directory.Exists(appData))
                Directory.CreateDirectory(appData);
            if (!File.Exists(appData + "data.dat"))
            {
                string storage = RandomString(15);
                string key = RandomString(15);
                using (StreamWriter sw = new StreamWriter(appData + "data.dat", false))
                {
                    sw.WriteLine(storage);
                    sw.WriteLine(key);
                }
            }
            LoadData();

            // Initialize the service.
            Service = new TasksService(CreateAuthenticator());

            Application.Run(new TasksForm(Service.Tasklists.List().Fetch().Items));
        }
    }
}
